#include"baseclass.h"
#include"rings.h"
using namespace std;

void addcarbon(void);//添加碳原子
void addtext(void);//添加文本
void contect(void);//连接
void addh(void);//补氢
void addgroup(void);//添加基团
void putlist(void);//输出单独添加的基团之列表
void addrings(void);//绘制多元环状结构
void editrings(void);//编辑
void getmass(void);//获取相对分子质量
void getreatcion(void);//查看可发生反应

//这几个API是来自prepareations.cpp的
extern int object_init(void);
extern int getgroupnumber(int a1, int a2);
extern int makespace(int n,int *ny);


extern short carbonnumber;
extern short groupswithoxygens;
extern short groupsunoxygens;
extern short alkylnumbers;
extern short ringnumbers;

int main()
{
	//绘图环境准备
	initgraph(1200, 800, SHOWCONSOLE);
	settextcolor(BLACK); setlinecolor(WHITE); setbkcolor(WHITE);
	for (int i = 1; i <= 800; i++){line(0, i, 1200, i);}
	outtextxy(100, 2, L"100");outtextxy(250, 2, L"250");
	outtextxy(500, 2, L"500");outtextxy(750, 2, L"750");
	outtextxy(1000, 2, L"1000");
	outtextxy(2, 200, L"200"); outtextxy(2, 400, L"400");
	outtextxy(2, 600, L"600"); 
	//设置图形界面的标尺
	settextstyle(40, 0, _T("Consolas")); setlinecolor(BLACK);

	object_init();//对象初始化

	for (;;)
	{
		cout<<"CarbonChem0.5 By TSherry\n";
		
		cout << "请选择需要的操作，输入对应的数字作为指令\n";
		printf_s("%-22s\t%-22s\n", "1.单独添加碳原子","2.添加基团");
		printf_s("%-22s\t%-22s\n", "3.连接原子或基团", "4.补氢");
		printf_s("%-22s\t%-22s\n", "5.添加文本", "6.输出基团(包括各种环)列表");
		printf_s("%-22s\t%-22s\n", "7.添加多元环状结构", "8.编辑多元环状结构");
		printf_s("%-22s\t%-22s\n", "9.输出相对分子质量","10.判断能发生什么反应");


		int descision = 0;
		scanf_s("%d", &descision);
		switch (descision)
		{
		case 1:addcarbon(); break;case 2:addgroup(); break;
		case 3:contect(); break;case 4:break;
		case 5:addtext(); break;case 6:putlist(); break;
		case 7:addrings(); break; case 8:editrings(); break;
		case 9:getmass(); break; case 10:getreatcion(); break;
		default:printf_s("指令输入错误，按任意键继续\n");
			_getch(); break;
		}system("cls");
	}

}

void addcarbon(void)//添加碳原子
{
	carbonnumber++; all++; cs[carbonnumber].kind = 1;
	printf_s("该碳原子的编号为%d\t请输入其横坐标和纵坐标\n",carbonnumber);
	cin >> cs[carbonnumber].x >> cs[carbonnumber].y;
	outtextxy(cs[carbonnumber].x, cs[carbonnumber].y, L"C");
		struct group newc; 
		newc.number = all;
		newc.x = cs[carbonnumber].x;
		newc.y = cs[carbonnumber].y;
		newc.unified = 30;
		newc.w_connect = false;
		newc.mass = 12.011;
		groups.push_back(newc); 
		cs[carbonnumber].rank = all;
}

void addgroup(void)//添加基团
{
	printf_s("要添加的是含氧的还是不含氧的?(1/0)\n");
	int a; cin >> a; if (a == 0)
	{
		cout << "要添加的基团是烃基吗?(1/0)" << endl;
		a=getchar();//把回车符读取了
		if (getchar()!= '0')
		{
			cout << "当前添加的是第" << (++alkylnumbers) << "个烃基\n";
			printf_s("请看是以下的哪种，然后输入对应的数字\n");
			for (int i = 1; i <= 12; i++)
			{
				//cout << i << alkylname[i] << "";
				printf_s("%d %-15s", i, alkylname[i]);
				if (i % 4 == 0)printf_s("\n");
			}
			printf_s("\n");
			cin >> alkyls[alkylnumbers].kind;
			printf_s("请输入其横坐标和纵坐标\t");
			cin >> alkyls[alkylnumbers].x >> alkyls[alkylnumbers].y;
			alkyls[alkylnumbers].put();

				struct group newg; all++;
				newg.number = all;
				newg.x = alkyls[alkylnumbers].x;
				newg.y = alkyls[alkylnumbers].y;
				newg.unified = alkyls[alkylnumbers].unified;
				newg.w_connect= false;
				newg.mass = alkyls[alkylnumbers].mass;
				groups.push_back(newg);
				alkyls[alkylnumbers].rank = all;
		}
		else {
			cout << "当前添加的是第" << (++groupsunoxygens) << "个不含氧基团\n";
			printf_s("请看是以下的哪种，然后输入对应的数字\n");
			for (int i = 1; i <= 9; i++)
			{
				printf_s("%d %-15s", i, groupunoxygenname[i]);
				if (i % 4 == 0)printf_s("\n");
			}
			printf_s("\n");
			cin >> ungs[groupsunoxygens].kind;
			printf_s("请输入其横坐标和纵坐标\t");
			cin >> ungs[groupsunoxygens].x >> ungs[groupsunoxygens].y;
			ungs[groupsunoxygens].put();
			
				struct group newg; all++;
				newg.number = all;
				newg.x = ungs[groupsunoxygens].x;
				newg.y = ungs[groupsunoxygens].y;
				newg.unified = ungs[groupsunoxygens].unified;
				newg.mass = ungs[groupsunoxygens].mass;
				newg.w_connect= false;
				if (newg.unified == 38 || (newg.unified >= 15 && newg.unified <= 18))
				{
					newg.left = newg.right = 0;
				}
				groups.push_back(newg);
				ungs[groupsunoxygens].rank = all;
		}
	}else {
		cout << "当前添加的是第" << (++groupswithoxygens) << "个含氧基团\n";
		printf_s("请看是以下的哪种，然后输入对应的数字\n");
		for (int i = 1; i <= 9; i++)
		{
			printf_s("%d %-15s", i, groupswithoxygenname[i]);
			if (i % 4 == 0)printf_s("\n");
		}
		printf_s("\n");
		cin >> gs[groupswithoxygens].kind;
		printf_s("请输入其横坐标和纵坐标\t");
		cin >> gs[groupswithoxygens].x >> gs[groupswithoxygens].y;
		gs[groupswithoxygens].put();

			struct group newg; all++;
			newg.number = all;
			newg.x = gs[groupswithoxygens].x;
			newg.y = gs[groupswithoxygens].y;
			newg.unified = gs[groupswithoxygens].unified;
			newg.mass = gs[groupswithoxygens].mass;
			newg.w_connect = false;
			if (newg.unified == 38 || (newg.unified >= 15 || newg.unified <= 18))
			{
				newg.left = newg.right = 0;
			}
			groups.push_back(newg);
			gs[groupswithoxygens].rank = all;
	}
	settextstyle(40, 0, _T("Consolas"));
}

void contect(void)//连接
{
	cout << "在整体的输入中，请问您要连接的两个单独添加的结构是哪两个结构?" << endl;
	cout << "它们分别是第几个输入的?请输入两个序号\n";
	int n1,n2;
	cin >> n1 >> n2;
	int x1, y1, x2, y2;
	//x1 = groups[n1-1].x; x2 = groups[n2-1].x;
	y1 = groups[n1-1].y; y2 = groups[n2-1].y;
	x1=makespace(n1-1,&y1); x2=makespace(n2-1,&y2);
	if (x1 == -1 || x2 == -1)return;
	line(x1 + 15, y1 + 15, x2 + 15, y2 + 15); 

	groups[n1 - 1].w_connect = groups[n2 - 1].w_connect = true;

	return;
}

void addtext(void)
{
	cout << "请输入要添加的文本内容:\t";
	wchar_t text; wscanf_s(L"%s", &text,(unsigned)sizeof(text));
	cout << "请输入文本显示的坐标:\t";
	int x, y; cin >> x >> y;
	outtextxy(x, y, text);
}

void putlist(void)
{
	
	cout << "面前一共单独添加的各种结构有" << all << "个" << endl;
	if (carbonnumber > 0)
	{
		cout << "\n==============================\n";
		printf_s("单独添加的碳原子有%d个，分别为:\n", alkylnumbers);
		carbon* p = cs + 1;
		carbon* q = cs;
		int s = sizeof(cs);
		while (p->kind != 0)
		{
			printf_s("编号\t坐标\t总序号\n");
			printf_s("%4d\t(%d,%d)\t%d\n", (int)(p - q),p->x, p->y,p->rank);
			p++;
		}
	}
	if(alkylnumbers>0)
	{
		cout << "\n==============================\n";
		printf_s("单独添加的烃基有%d个，分别为:\n", alkylnumbers);
		alkyl* p = alkyls + 1;
		alkyl* q = alkyls;
		int s = sizeof(alkyl);
		while (p->kind != 0)
		{
			printf_s("编号\t种类标识\t坐标\t总序号\n");
			printf_s("%4d\t%4d\t\t(%d,%d)\t%d\n", (int)(p - q), p->unified, p->x, p->y, p->rank);
			p++;
		}
	}if(groupswithoxygens>0)
	{
		cout << "\n==============================\n";
		printf_s("单独添加的含氧基团有%d个，分别为:\n", groupswithoxygens);
		groupwithoxygen* p=gs+1;
		groupwithoxygen* q = gs;
		int s = sizeof(groupwithoxygen);
		while (p->kind != 0)
		{
			printf_s("编号\t种类标识\t坐标\t总序号\n");
			printf_s("%4d\t%4d\t\t(%d,%d)\t%d\n", (int)(p - q), p->unified, p->x, p->y, p->rank);
			p++;
		}
	}if(groupswithoxygens>0)
	{
		cout << "\n==============================\n";
		printf_s("单独添加的不含氧基团(非烃基)有%d个，分别为:\n", groupswithoxygens);
		groupwithoutoxygen* p = ungs + 1;
		groupwithoutoxygen* q = ungs;
		int s = sizeof(groupwithoxygen);
		while (p->kind != 0)
		{
			printf_s("编号\t种类标识\t坐标\t总序号\n");
			printf_s("%4d\t%4d\t\t(%d,%d)\t%d\n", (int)(p - q), p->unified, p->x, p->y, p->rank);
			p++;
		}
	}
	if (ringnumbers > 0)
	{
		cout << "\n==============================\n";
		printf_s("单独添加的多元环状结构有%d个，分别为:\n", ringnumbers);
		ring* p = rings + 1;
		ring* q = rings;
		int s = sizeof(ring);
		while (p->elementnumber!= 0)
		{
			printf_s("编号\t元数\t坐标\t总序号\n");
			printf_s("%4d\t%4d\t(%d,%d)\t%d\n", (int)(p - q), p->elementnumber, p->x, p->y, p->rank);
			p++;
		}
	}
	printf_s("按任意键继续\n"); _getch();
}

void addrings(void)//增设多元的环状结构
{
	cout << "这是第" << ++ringnumbers << "个多元环状结构\n";
	cout<<"请输入要设置为几元环(最少是三元环，最多支持八元环)\t";
	short a; cin >> a;
	if (a < 3 || a>8) //输入错误的处理
	{ cout << "元数错误！按任意键继续\n"; _getch(); ringnumbers--; return; }
	cout << "请输入坐标(x,y)\t"; cin >> rings[ringnumbers].x >> rings[ringnumbers].y;
	rings[ringnumbers].elementnumber = a;

	//设置其包含的碳原子之各项属性
	int i;//这个是要遍历的环中每一个碳原子的编号
	for (i = 1; i <= a; i++)
	{
		rings[ringnumbers].elements[i].x = rings[ringnumbers].x + dertax[a - 2][i];
		rings[ringnumbers].elements[i].y = rings[ringnumbers].y + dertay[a - 2][i];
		rings[ringnumbers].elements[i].number=i;
	}//设置其不包含的碳原子之各项属性
	for (; i <= 8; i++) {
		rings[ringnumbers].elements[i].x = rings[ringnumbers].x + dertax[a - 2][i];
		rings[ringnumbers].elements[i].y = rings[ringnumbers].y + dertay[a - 2][i];
		rings[ringnumbers].elements[i].kind = 0;
		rings[ringnumbers].elements[i].remain = 0;
	}

		struct group newg; all++;
		newg.number = all;
		newg.x = rings[ringnumbers].x;
		newg.y = rings[ringnumbers].y;
		newg.unified = rings[ringnumbers].elementnumber+28;
		newg.w_connect = false;
		groups.push_back(newg);
		rings[ringnumbers].rank = all;//获取在所有内容中的序号
	rings[ringnumbers].put();//输出

	return;
}

void editrings(void)
{
	cout << "当前有" << ringnumbers << "个单独添加的多元环状结构\n";
	cout << "请输入要编辑的是哪一个  "; short a; cin >> a;
	if(a<0||a>ringnumbers)
	{cout << "序号错误！按任意键继续\n"; _getch();  return;}
	cout << "当前对应的坐标是(" << rings[a].x << ',' << rings[a].y << ")\n";
	cout << "请输入所需要执行的操作:1.添加碳碳双键或三键\t2.改环上的碳原子为其它原子\n";
	short b; cin >> b;
	if (b == 1) {//添加碳碳双键或三键
		cout << "请按照碳原子自左上角开始顺时针的顺序编号,输入所要添加的不饱和键两端,";
		cout << "编号较小的那一个(如果是第一个和最后一个之间，输入最后一个的编号)\n";
		int m; cin >> m;
		if(m<1||m>rings[a].elementnumber)
		{cout << "输入的操作有误！按任意键继续\n"; _getch(); return;}
		cout << "所要添加的是碳碳双键还是碳碳三键?(2/3)  "; int u; cin >> u;
		rings[a].add_unsaturated(m, u);
	}
	else if (b == 2) {//改环上的碳原子为其它原子
		int site; wchar_t name[3];
		cout << "请输入要修改的碳原子编号:  ";
		cin >> site; 
		cout << "请输入要修改成的原子的元素符号:  ";
		wcin >> name;
		rings[a].changeatom(site, name);
	}
	else {cout << "输入的操作有误！按任意键继续\n"; _getch(); return;}
}

void addh(void)
{
	/*因为我们补氢只是在碳原子上补，而碳原子中只有单独添加的
	才有可能存在这个需要，所以只需在单独添加的碳原子上处理即可*/
	for (int i = 1; i <= carbonnumber; i++)
	{
		if (cs[i].remain > 0)
		{
			outtextxy(cs[i].x + 20, cs[i].y, L"H");
			settextstyle(25, 0, _T("Consolas"));
			switch (cs[i].remain)
			{
			case 2:outtextxy(cs[i].x + 40, cs[i].y + 15, L"2"); break;
			case 3:outtextxy(cs[i].x + 40, cs[i].y + 15, L"3"); break;
			case 4:outtextxy(cs[i].x + 40, cs[i].y + 15, L"4"); break;
			default:break;
			}
			
		}
	}
}

void getmass(void)
{
	for (int i = 1; i <= all; i++)
	{
		themass += groups[i].mass;
	}
	cout << "相对分子质量为:  " << themass << endl;
	_getch();
}

void getreatcion(void)
{
	set<reaction>r;
	for (int i = 0; i <= all; i++)
	{
		switch (groups[i].unified)
		{
		case 1:case 2:case 3:case 5:case 6:
		case 20:case 21:case 22:
			r.insert(substitute); break;
		case 7:
			r.insert(substitute); r.insert(esterification);
			r.insert(neutraliation); r.insert(oxidize);break;
		case 8:
			r.insert(oxidize); r.insert(restore); break;
		case 15:
			r.insert(oxidize); r.insert(restore); r.insert(add); break;
		case 9:case 19:r.insert(substitute); r.insert(esterification);
			r.insert(neutraliation); r.insert(restore); break;
		case 10:
			r.insert(peptide); r.insert(substitute); break;
		case 11:case 23:r.insert(add); break;
		case 12:r.insert(substitute); r.insert(add); break;
		case 13:case 14:r.insert(restore); break;
		case 16:case 18:r.insert(hydrolysis); r.insert(substitute); break;
		case 38:r.insert(restore); break;
		}

	}
	set<reaction>::iterator a;
	cout << "根据基团种类来判断，一定会发生的反应有:\n";
	for (a = r.begin(); a != r.end(); a++)
	{
		switch (*a)
		{
		case substitute:printf_s("取代反应\t"); break;
		case add:printf_s("加成反应\t"); break;
		case elimination:printf_s("消去反应\t"); break;
		case hydrolysis:printf_s("水解反应\t"); break;
		case esterification:printf_s("酯化反应\t"); break;
		case neutraliation:printf_s("酸碱中和反应\t"); break;
		case oxidize:printf_s("氧化反应\t"); break;
		case restore:printf_s("还原反应\t"); break;
		case peptide:printf_s("成肽反应\t"); break;
		default:continue;
		}
	}
	set<reaction>s;
	for (int i = 1; i <= all; i++)
	{
		switch (groups[i].unified)
		{
		case 7:s.insert(elimination); break;
		case 25:case 26:case 27:case 28:
			s.insert(add); s.insert(substitute); break;
		case 31:case 32:case 33:
		case 34:case 35:case 36:
			s.insert(substitute); break;
		}
	}
	cout << "===========================================\n";
	set<reaction>::iterator b;
	cout << "\n根据基团种类来判断，可能会发生的反应有:\n";
	for (b = s.begin(); b != s.end(); b++)
	{
		switch (*b)
		{
		case substitute:printf_s("取代反应\t"); break;
		case add:printf_s("加成反应\t"); break;
		case elimination:printf_s("消去反应\t"); break;
		case hydrolysis:printf_s("水解反应\t"); break;
		case esterification:printf_s("酯化反应\t"); break;
		case neutraliation:printf_s("酸碱中和反应\t"); break;
		case oxidize:printf_s("氧化反应\t"); break;
		case restore:printf_s("还原反应\t"); break;
		case peptide:printf_s("成肽反应\t"); break;
		default:continue;
		}
	}
	cout << "===========================================\n";
	cout << "\n注意:其中的反应类型不包括燃烧对应的氧化反应，因为几乎所有的有机物都可燃\n";
	_getch();
}